#pragma once

#include "localsocket.hpp"
#include "localconnection.hpp"

namespace Local_Connection
{

#define SIZE 1024


    class LocalChannel : public LocalConnection
    {
    public:
        /**********构造析构************** */
        LocalChannel(const int sockfd, const Local_Inetaddr::Inetaddr &client_addr)
            : _sockfd(sockfd), _client_addr(client_addr)
        {
            SetNonBlock(_sockfd);
        }
        ~LocalChannel() {}

        /**********virtual************** */
        void Recver() override
        {
            Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "LocalChannel Recver ";
            char lo_buffer[SIZE];
            while (true)
            {
                lo_buffer[0] = 0;                                                        // 清空字符串
                ssize_t ret_rec = recv(_sockfd, lo_buffer, sizeof(lo_buffer) - 1, 0); // 非阻塞读
                if (ret_rec > 0)
                {
                    // 读取成功
                    lo_buffer[ret_rec] = 0;
                    _inbuffer += lo_buffer;
                }
                else if (ret_rec == 0)
                {
                    // 文件描述符关闭错误
                    Excepter();
                    return;
                }
                else
                {
                    // 被信号终止
                    if (errno == EAGAIN || errno == EWOULDBLOCK)
                    {
                        // 读阻塞
                        break;
                    }
                    else if (errno == EINTR)
                    {
                        continue;
                    }
                    else
                    {
                        // 其他错误
                        Excepter();
                        return;
                    }
                }
            }
            Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "LocalChannel Recver :\n"
                                                        << _inbuffer;
            if (!_inbuffer.empty())
            {
                // 回调将 inbuffer 传输出去 将 outbuffer 接受回来
                _outbuffer += _handler(_inbuffer);
            }
            if (!_outbuffer.empty())
            {
                Sender(); // 最佳
                // GetOwner()->EnableReadWrite(_sockfd, true, true);
            }
        }
        void Sender() override
        {
            Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "LocalChannel Sender ";
            while (true)
            {
                ssize_t ret_sen = send(_sockfd, _outbuffer.c_str(), _outbuffer.size(), 0);
                if (ret_sen > 0)
                {
                    // 发送成功
                    _outbuffer.erase(0, ret_sen);
                    // 发送完成
                    if (_outbuffer.empty())
                        break;
                }
                else if (ret_sen == 0)
                {
                    // 文件描述符关闭
                    break;
                }
                else
                {
                    // 被信号终止
                    if (errno == EAGAIN || errno == EWOULDBLOCK)
                    {
                        // 被阻塞
                        break;
                    }
                    else if (errno == EINTR)
                    {
                        continue;
                    }
                    else
                    {
                        // 写错误
                        Excepter();
                        return;
                    }
                }
            }
            // 情况1：数据发送完毕
            // 情况2：发送条件不具备
            if (!_outbuffer.empty())
            {
                // 有数据未发送，代表写阻塞，开启对写事件的关心
                GetReactor()->EnableReadWrite(_sockfd, true, true);
            }
            else
            {
                // 发送缓冲区空，代表写完成，关闭对写事件的关心
                GetReactor()->EnableReadWrite(_sockfd, true, false);
            }
        }
        void Excepter() override
        {
            Local_Log::LOG(Local_Log::LogLever::LDEBUG) << "LocalChannel Excepter ";
            GetReactor()->DelConnection(_sockfd);
        }
        int GetsockFd() override
        {
            return _sockfd;
        }

        /**********GetSet************** */

    private:
        // fd
        int _sockfd;

        std::string _inbuffer; // 缓冲区 vector<char>
        std::string _outbuffer;

        // client info
        Local_Inetaddr::Inetaddr _client_addr;

    };
}